home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / dev / cross / devpic.lha / picasm-src / expr.c < prev    next >
C/C++ Source or Header  |  1998-05-04  |  8KB  |  429 lines

  1. /*
  2.  * picasm -- expr.c
  3.  *
  4.  * expression parser
  5.  *
  6.  * Timo Rossi <trossi@iki.fi>
  7.  * 
  8.  */
  9.  
  10. #include <stdio.h>
  11. #include <string.h>
  12.  
  13. #include "picasm.h"
  14.  
  15. int expr_error; /* expression error flag */
  16.  
  17. /*
  18.  * expression parser, bottom level
  19.  */
  20. static long
  21. expr_element(void)
  22. {
  23.   long val, tval;
  24.   struct symbol *sym;
  25.   static unsigned char strbuf[256];
  26.   int symtype;
  27.  
  28.   if(expr_error)
  29.     return 0;
  30.     
  31.   switch(token_type) {
  32.     case TOK_LEFTBRAK:
  33.       get_token();
  34.       tval = 0;
  35.       while(!expr_error && token_type != TOK_RIGHTBRAK) {
  36.     val = get_expression();
  37.     if(val < 0 || val >= EXPR_NBITS) {
  38.       error(1, "bit number out of range");
  39.       expr_error = 1;
  40.     }
  41.     tval |= (1 << val);
  42.       }
  43.       if(!expr_error)
  44.     get_token();
  45.       return tval;
  46.  
  47.     case TOK_LEFTPAR:
  48.       get_token();
  49.       val = get_expression();
  50.       if(!expr_error && token_type != TOK_RIGHTPAR) {
  51.     error(1, "')' expected");
  52.     expr_error = 1;
  53.       }
  54.       if(!expr_error)
  55.     get_token();
  56.       return val;
  57.  
  58.     case KW_DEFINED:
  59.       get_token();
  60.       if(token_type != TOK_LEFTPAR) {
  61.     error(1, "'(' expected");
  62.     expr_error = 1;
  63.     return EXPR_FALSE;
  64.       }
  65.  
  66.       get_token();
  67.       if(token_type != TOK_IDENTIFIER && token_type != TOK_LOCAL_ID) {
  68.     error(1, "Symbol expected");
  69.     expr_error = 1;
  70.     return EXPR_FALSE;
  71.       }
  72.  
  73.       symtype =
  74.     (token_type == TOK_IDENTIFIER ? SYMTAB_GLOBAL : SYMTAB_LOCAL);
  75.  
  76.       if((sym = lookup_symbol(token_string, symtype)) == NULL)
  77.     val = EXPR_FALSE;
  78.       else if(sym->type == SYM_DEFINED || sym->type == SYM_SET)
  79.     val = EXPR_TRUE;
  80.       else
  81.     val = EXPR_FALSE;
  82.  
  83.       get_token();
  84.       if(token_type != TOK_RIGHTPAR) {
  85.     error(1, "')' expected");
  86.     expr_error = 1;
  87.     return val;
  88.       }
  89.       get_token();
  90.       return val;
  91.  
  92.     case KW_STREQ:
  93.       /* streq(arg1, arg2), return TRUE if strings are identical */
  94.       get_token();
  95.       if(token_type != TOK_LEFTPAR) {
  96.     error(1, "'(' expected");
  97.     expr_error = 1;
  98.     return EXPR_FALSE;
  99.       }
  100.  
  101.       get_token();
  102.       if(token_type != TOK_STRCONST) {
  103.     error(1, "Quoted string expected");
  104.     expr_error = 1;
  105.     return EXPR_FALSE;
  106.       }
  107.       strcpy(strbuf, token_string);
  108.  
  109.       get_token();
  110.       if(token_type != TOK_COMMA) {
  111.     error(1, "',' expected");
  112.     expr_error = 1;
  113.     return EXPR_FALSE;
  114.       }
  115.  
  116.       get_token();
  117.       if(token_type != TOK_STRCONST) {
  118.     error(1, "Quoted string expected");
  119.     expr_error = 1;
  120.     return EXPR_FALSE;
  121.       }
  122.  
  123.       val = (strcmp(token_string, strbuf) == 0 ? EXPR_TRUE : EXPR_FALSE);
  124.  
  125.       get_token();
  126.       if(token_type != TOK_RIGHTPAR) {
  127.     error(1, "')' expected");
  128.     expr_error = 1;
  129.     return val;
  130.       }
  131.       get_token();
  132.       return val;
  133.  
  134.     case KW_ISSTR:
  135.       /* isstr(arg), return TRUE if argument is a quoted string */
  136.       get_token();
  137.       if(token_type != TOK_LEFTPAR) {
  138.     error(1, "'(' expected");
  139.     expr_error = 1;
  140.     return EXPR_FALSE;
  141.       }
  142.  
  143.       get_token();
  144.       if(token_type == TOK_STRCONST) {
  145.     val = EXPR_TRUE;
  146.     get_token();
  147.       }    else if(token_type == TOK_RIGHTPAR) {
  148.     get_token(); /* empty parameter list */
  149.     return EXPR_FALSE;
  150.       } else {
  151.     val = EXPR_FALSE;
  152.     do {
  153.       get_token();
  154.     } while(token_type != TOK_EOF && token_type != TOK_NEWLINE &&
  155.         token_type != TOK_COMMA && token_type != TOK_RIGHTPAR);
  156.       }
  157.       if(token_type != TOK_RIGHTPAR) {
  158.     error(1, "')' expected");
  159.     expr_error = 1;
  160.     return val;
  161.       }
  162.       get_token();
  163.       return val;
  164.  
  165.     case KW_CHRVAL:
  166.       /* chrval(string, pos), return ascii code of character in string */
  167.       get_token();
  168.       if(token_type != TOK_LEFTPAR) {
  169.     error(1, "'(' expected");
  170.     expr_error = 1;
  171.     return -1;
  172.       }
  173.  
  174.       get_token();
  175.       if(token_type != TOK_STRCONST) {
  176.     error(1, "Quoted string expected");
  177.     expr_error = 1;
  178.     return -1;
  179.       }
  180.       strcpy(strbuf, token_string);
  181.  
  182.       get_token();
  183.       if(token_type != TOK_COMMA) {
  184.     error(1, "',' expected");
  185.     expr_error = 1;
  186.     return -1;
  187.       }
  188.  
  189.       get_token();
  190.       val = get_expression();
  191.       if(val < 0 || val >= (long)strlen(strbuf))
  192.     val = -1;
  193.       else
  194.     val = strbuf[val];
  195.  
  196.       if(token_type != TOK_RIGHTPAR) {
  197.     error(1, "')' expected");
  198.     expr_error = 1;
  199.     return val;
  200.       }
  201.       get_token();
  202.       return val;
  203.  
  204.     case TOK_DOLLAR: /* current location */
  205.     case TOK_PERIOD:
  206.       switch(O_Mode) {
  207.         case O_PROGRAM:
  208.       val = prog_location;
  209.       break;
  210.  
  211.     case O_REGFILE:
  212.       val = reg_location;
  213.       break;
  214.  
  215.     case O_EDATA:
  216.       val = edata_location;
  217.       break;
  218.  
  219.     case O_NONE:
  220.     default:
  221.       val = org_val;
  222.       break;
  223.       }
  224.       if(val < 0) {
  225.     error(1, "ORG value not set");
  226.     expr_error = 1;
  227.       }
  228.       get_token();
  229.       return val;
  230.  
  231.     case TOK_INTCONST:
  232.       val = token_int_val;
  233.       get_token();
  234.       return val;
  235.  
  236.     case TOK_IDENTIFIER:
  237.     case TOK_LOCAL_ID:
  238.       symtype =
  239.     (token_type == TOK_IDENTIFIER ? SYMTAB_GLOBAL : SYMTAB_LOCAL);
  240.  
  241.       if(symtype == SYMTAB_LOCAL && local_level == 0) {
  242.     error(1, "Local symbol outside a LOCAL block");
  243.     expr_error = 1;
  244.     return 0;
  245.       }
  246.  
  247.       if((sym = lookup_symbol(token_string, symtype)) == NULL) {
  248.     error(1, "Undefined symbol '%s%s'",
  249.           (symtype == SYMTAB_LOCAL ? "=" : ""),
  250.           token_string);
  251.     expr_error = 1;
  252.       }    else {
  253.     if(sym->type == SYM_MACRO) {
  254.       error(1, "Invalid usage of macro name '%s'", token_string);
  255.       expr_error = 1;
  256.     } else if(sym->type != SYM_DEFINED && sym->type != SYM_SET) {
  257.       error(1, "Undefined symbol '%s%s'",
  258.         (symtype == SYMTAB_LOCAL ? "=" : ""),
  259.         token_string);
  260.       expr_error = 1;
  261.     }
  262.  
  263.     get_token();
  264.     return sym->v.value;
  265.       }
  266.       break;
  267.  
  268.     default:
  269.       expr_error = 1;
  270.       error(1, "Expression syntax error");
  271.       break;
  272.   }
  273.  
  274.   return 0;
  275. }
  276.  
  277. /* expression parser, unary minus and bit-not */
  278. static long
  279. expr_unary1(void)
  280. {
  281.   int op;
  282.   long val;
  283.  
  284.   if(!expr_error &&
  285.      (token_type == TOK_MINUS || token_type == TOK_BITNOT)) {
  286.     op = token_type;
  287.     get_token();
  288.     val = expr_element();
  289.     if(op == TOK_MINUS)
  290.       return -val;
  291.     else
  292.       return ~val;
  293.   } else
  294.     return expr_element();
  295. }
  296.  
  297. /* expression, multiplication, division, bit-and */
  298. static long
  299. expr_mul_div(void)
  300. {
  301.   int op;
  302.   long val1, val2;
  303.  
  304.   val1 = expr_unary1();
  305.   while(!expr_error &&
  306.     ((op = token_type) == TOK_ASTERISK || op == TOK_SLASH ||
  307.      op == TOK_PERCENT || op == TOK_BITAND)) {
  308.     get_token();
  309.     val2 = expr_unary1();
  310.     switch(op) {
  311.       case TOK_ASTERISK:
  312.         val1 *= val2;
  313.     break;
  314.  
  315.       case TOK_SLASH:
  316.       case TOK_PERCENT:
  317.     if(val2 == 0) {
  318.       error(1, "Division by zero");
  319.       expr_error = 1;
  320.     } else {
  321.       if(op == TOK_SLASH)
  322.         val1 /= val2;
  323.       else
  324.         val1 %= val2;
  325.     }
  326.     break;
  327.  
  328.       case TOK_BITAND:
  329.     val1 &= val2;
  330.     break;
  331.     }
  332.   }
  333.   return val1;
  334. }
  335.  
  336. /* expression. add, subtract, bit-or */
  337. static long
  338. expr_add_sub(void)
  339. {
  340.   int op;
  341.   long val1, val2;
  342.  
  343.   val1 = expr_mul_div();
  344.   while(!expr_error && ((op = token_type) == TOK_PLUS || op == TOK_MINUS ||
  345.                op == TOK_BITOR || op == TOK_BITXOR ||
  346.                op == TOK_LSHIFT || op == TOK_RSHIFT)) {
  347.     get_token();
  348.     val2 = expr_mul_div();
  349.     switch(op) {
  350.       case TOK_PLUS:
  351.         val1 += val2;
  352.     break;
  353.  
  354.       case TOK_MINUS:
  355.     val1 -= val2;
  356.     break;
  357.  
  358.       case TOK_BITOR:
  359.     val1 |= val2;
  360.     break;
  361.  
  362.       case TOK_BITXOR:
  363.     val1 ^= val2;
  364.     break;
  365.  
  366.       case TOK_LSHIFT:
  367.     val1 <<= val2;
  368.     break;
  369.  
  370.       case TOK_RSHIFT:
  371.     val1 >>= val2;
  372.     break;
  373.       }
  374.   }
  375.   return val1;
  376. }
  377.  
  378. /*
  379.  * the main expression parser entry point
  380.  *
  381.  * handles only compare operators directly
  382.  * (note: '=' (TOK_EQUAL) cannot be used as a comparison operator
  383.  * as it would be confused with local labels. '==' (TOK_EQ)
  384.  * must be used instead)
  385.  */
  386. long
  387. get_expression(void)
  388. {
  389.   int op;
  390.   long val1, val2;
  391.  
  392.   expr_error = 0;
  393.  
  394.   val1 = expr_add_sub();
  395.   while(!expr_error && ((op = token_type) == TOK_EQ ||
  396.                op == TOK_NOT_EQ ||
  397.                op == TOK_LESS || op == TOK_GREATER ||
  398.                op == TOK_LESS_EQ || op == TOK_GT_EQ)) {
  399.     get_token();
  400.     val2 = expr_add_sub();
  401.     switch(op) {
  402.       case TOK_EQ:
  403.         val1 = -(val1 == val2);
  404.     break;
  405.  
  406.       case TOK_NOT_EQ:
  407.     val1 = -(val1 != val2);
  408.     break;
  409.  
  410.       case TOK_LESS:
  411.     val1 = -(val1 < val2);
  412.     break;
  413.  
  414.       case TOK_LESS_EQ:
  415.     val1 = -(val1 <= val2);
  416.     break;
  417.  
  418.       case TOK_GREATER:
  419.     val1 = -(val1 > val2);
  420.     break;
  421.  
  422.       case TOK_GT_EQ:
  423.     val1 = -(val1 >= val2);
  424.     break;
  425.     }
  426.   }
  427.   return val1;
  428. }
  429.